package cn.tedu.xxmall.service.impl;

import cn.tedu.xxmall.ex.ServiceException;
import cn.tedu.xxmall.mapper.AdminMapper;
import cn.tedu.xxmall.mapper.AdminRoleMapper;
import cn.tedu.xxmall.pojo.dto.AdminAddNewDTO;
import cn.tedu.xxmall.pojo.dto.AdminLoginDTO;
import cn.tedu.xxmall.pojo.entity.Admin;
import cn.tedu.xxmall.pojo.entity.AdminRole;
import cn.tedu.xxmall.pojo.vo.AdminLoginVO;
import cn.tedu.xxmall.security.AdminDetail;
import cn.tedu.xxmall.service.IAdminService;
import cn.tedu.xxmall.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private AdminRoleMapper adminRoleMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Value("${xxmall.jwt.secretKey}")
    private String secretKey;

    @Value("${xxmall.jwt.dateTime}")
    private Long dateTime;

    public AdminServiceImpl() {
        log.debug("创建管理员业务处理类");
    }

    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        log.debug("开始处理添加管理员业务");
        AdminLoginVO adminLoginVO = adminMapper.selectByUserName(adminAddNewDTO.getUsername());
        if (adminLoginVO != null) {
            //报错
            String message = "用户名已存在";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        Admin admin = new Admin();
        //将传输过来的DTO数据复制到admin里面存入数据库
        BeanUtils.copyProperties(adminAddNewDTO, admin);
        //对密码进行加密
        String password = admin.getPassword();
        String encode = passwordEncoder.encode(password);
        admin.setPassword(encode);
        int rows = adminMapper.insert(admin);
        if (rows < 1) {
            // 是：日志，抛出ServiceException
            String message = "添加管理员失败，服务器忙，请稍后再次尝试！[错误代码：1]";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        //处理权限
        log.debug("开始处理权限关联");
        Long[] roleIds = adminAddNewDTO.getRoleIds();
        AdminRole[] adminRoles = new AdminRole[roleIds.length];
        for (int i = 0; i < adminRoles.length; i++) {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(admin.getId());
            adminRole.setRoleId(roleIds[i]);
            adminRoles[i] = adminRole;
        }
        int i = adminRoleMapper.addAdminRole(adminRoles);
        if (i<1){
            String message = "添加管理员失败，服务器忙，请稍后再次尝试！[错误代码：2]";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        log.debug("添加权限完成");
    }

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        log.debug("开始处理管理员登录业务");
        Authentication authentication = new UsernamePasswordAuthenticationToken(adminLoginDTO.getUsername(), adminLoginDTO.getPassword());
        Authentication authenticateResult = authenticationManager.authenticate(authentication);
        log.debug("认证通过！");
        AdminDetail loginUser = (AdminDetail) authenticateResult.getPrincipal();
        log.debug("认证结果中的管理员id：{}", loginUser.getId());
        log.debug("认证结果中的用户名：{}", loginUser.getUsername());
        Collection<GrantedAuthority> authorities = loginUser.getAuthorities();
        String authorityListString = JSON.toJSONString(authorities);
        Long id = loginUser.getId();
        log.debug("准备生成JWT");
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", id);
        claims.put("username", loginUser.getUsername());
        claims.put("authorities", authorityListString);
        log.debug("生成JWT，向JWT中存入username：{}", loginUser.getUsername());
        log.debug("生成JWT，向JWT中存入authorities：{}", authorityListString);
        String jwt = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "jwt")
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + dateTime * 60 * 1000))
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("生成的JWT：{}", jwt);
        return jwt;
    }

    @Override
    public void delete(Admin admin) {
        AdminLoginVO adminLoginVO = adminMapper.selectByUserName(admin.getUsername());
        if (adminLoginVO == null) {
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, "未找到此管理员信息");
        }
        int i = adminMapper.deleteByUserName(admin.getUsername());
        if (i == 0) {
            throw new ServiceException(
                    ServiceCode.ERR_INTERNAL_SERVER_ERROR, "删除失败，未知错误");
        }
    }

}
